/*
  spr-sdk: Statistical Pattern Recognition SDK
  Copyright (C) 2010 Marco Ambu

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _PR_NMC_H
#define _PR_NMC_H

#include "util/Real.h"
#include "pr/Classifier.h"

namespace pr {

class NearestMeanClassifier : public Classifier
{
public:
  NearestMeanClassifier(std::size_t numClasses, std::size_t numFeatures);

  virtual std::size_t classCount() const { return numClasses_; }
  virtual std::size_t featureCount() const { return numFeatures_; }

  virtual void train(const Pattern& trainingPattern, std::size_t classId);
  virtual std::size_t classify(const Pattern& testPattern);
  virtual bool test(const Pattern& testPattern, std::size_t classId);
  virtual bool rank(const Pattern& testPattern, std::size_t classId, std::size_t rank);

  bool classifyAndTrain(const Pattern& trainingPattern, std::size_t classId);

  const Pattern& mean(std::size_t classId);     // Returns the mean vector of class classlabel
  std::size_t patternCount(std::size_t classId);  // Returns the number of pattern used for each class during training

private:
  void update(const Pattern& trainingPattern, std::size_t classId);  // Training with a single vector without reset

private:
  class Category
  {
  public:
    Category(const Pattern& meanPattern, std::size_t patternCount, util::Real emissionProbability = 1.0)
      : meanPattern_(meanPattern), patternCount_(patternCount), emissionProbability_(emissionProbability)
    {}

    void addPattern(const Pattern& trainingPattern);

    const Pattern& mean() const { return meanPattern_; }
    std::size_t patternCount() const { return patternCount_; }
    util::Real emissionProbability() const { return emissionProbability_; }

    private:
      Pattern meanPattern_;
      std::size_t patternCount_;
      util::Real emissionProbability_;
  };

  typedef std::vector<Category>::const_iterator const_iterator;
  typedef std::vector<Category>::iterator iterator;
  
private:
  std::size_t numClasses_;
  std::size_t numFeatures_;
  std::vector<Category> classes_;
};

} // namespace pr

#endif // _PR_NMC_H
